#include "checktool.h"

CheckTool::CheckTool(QObject *parent) : QObject(parent)
{

}

void CheckTool::initTargetConfig()
{
  try{
    //初始化校准变量
    for(int i = 0;i < TargetNumber;i++){
        QString ID = QString::number(i);
        //写入全局变量
        TargetConfig.RakesMap[ID].LeftDownPoint.X = initConfig.getXorY(ID,"left-down-point","x");
        TargetConfig.RakesMap[ID].LeftDownPoint.Y = initConfig.getXorY(ID,"left-down-point","y");
        TargetConfig.RakesMap[ID].RightUpPoint.X = initConfig.getXorY(ID,"right-up-point","x");
        TargetConfig.RakesMap[ID].RightUpPoint.Y = initConfig.getXorY(ID,"right-up-point","y");
        TargetConfig.RakesMap[ID].ScaleFactor.X = initConfig.getXorY(ID,"scale-factor","x");
        TargetConfig.RakesMap[ID].ScaleFactor.Y = initConfig.getXorY(ID,"scale-factor","y");
      }
    qDebug() << "初始化校准变量 已完成";

  }
  catch(std::exception &ex)
  {
    qDebug() << "初始化校准变量异常";
    return ;
  }
}

// SaveCalibrationData
//
//	@Desc: 保存校准数据
//	@param ID
void CheckTool::SaveCalibrationData(int ID)
{

  QVector<BulletPoint> points = Container[ID];

  if(!points.size()){
      qDebug() << "无此靶校准数据";
      return ;
    }

  bool ret = WriteConfigFile(ID,points);

  if(!ret){
      qDebug() << "写入文件失败";
    }

}

bool CheckTool::WriteConfigFile(int ID, const QVector<BulletPoint>& points)
{
  Rake tempRake;

  tempRake = checkOrigin(points);

  if(!checkDataIsLegal(tempRake)){
      qDebug() << "校准数据不合法";
      return false;
    }

  //修改全局变量
  TargetConfig.RakesMap[QString::number(ID)].LeftDownPoint.X = tempRake.LeftDownPoint.X;
  TargetConfig.RakesMap[QString::number(ID)].LeftDownPoint.Y = tempRake.LeftDownPoint.Y;
  TargetConfig.RakesMap[QString::number(ID)].RightUpPoint.X = tempRake.RightUpPoint.X;
  TargetConfig.RakesMap[QString::number(ID)].RightUpPoint.Y = tempRake.RightUpPoint.Y;
  TargetConfig.RakesMap[QString::number(ID)].ScaleFactor.X = tempRake.ScaleFactor.X;
  TargetConfig.RakesMap[QString::number(ID)].ScaleFactor.Y = tempRake.ScaleFactor.Y;

  //写入文件

  bool ret1 = initConfig.setArgXY(QString::number(ID),"left-down-point",tempRake.LeftDownPoint.X,tempRake.LeftDownPoint.Y);
  bool ret2 = initConfig.setArgXY(QString::number(ID),"right-up-point",tempRake.RightUpPoint.X,tempRake.RightUpPoint.Y);
  bool ret3 = initConfig.setArgXY(QString::number(ID),"scale-factor",tempRake.ScaleFactor.X,tempRake.ScaleFactor.Y);

  if(ret1 && ret2 && ret3){
      qDebug() << "成功写入配置文件";
    }else{
      qDebug() << "写入配置文件失败！";
    }

  qDebug() << QString("左下 {x=%1 ,y=%2 }.右上 {x=%3 ,y=%4 }.放缩 {kX=%5 ,kY=%6 }.")
              .arg(tempRake.LeftDownPoint.X).arg(tempRake.LeftDownPoint.Y).arg(tempRake.RightUpPoint.X).arg(tempRake.RightUpPoint.Y)
              .arg(tempRake.ScaleFactor.X).arg(tempRake.ScaleFactor.Y);
  qDebug() << QString("w : %1, h : %2").arg(tempRake.RightUpPoint.X - tempRake.LeftDownPoint.X).arg(tempRake.RightUpPoint.Y - tempRake.LeftDownPoint.Y);

  return true;

}

Rake CheckTool::checkOrigin(const QVector<BulletPoint>& points)
{


  QVector<BulletPoint> pointsL,pointsR;

  for(int i = 0;i < points.size();i++){
      if(points[i].X > 0.9){
          qDebug() << QString("当前点X : %1,大于预定值(0.9)").arg(points[i].X);

          continue;
        }
      if(points[i].X < 0.6){
          pointsL.append(points[i]);
        }else{
          pointsR.append(points[i]);
        }
    }

  BulletPoint pointXYL,pointXYR;

  pointXYL = CheckPoints(pointsL);

  pointXYR = CheckPoints(pointsR);

  //求放缩值
  double kX = WeightOfTargetPaper * 1.0 / (pointXYR.X - pointXYL.X);
  double kY = HeightOfTargetPaper * 1.0 / (pointXYR.Y - pointXYL.Y);

  Rake tempRake;

  tempRake.LeftDownPoint.X = pointXYL.X;
  tempRake.LeftDownPoint.Y = pointXYL.Y;
  tempRake.RightUpPoint.X = pointXYR.X;
  tempRake.RightUpPoint.Y = pointXYR.Y;
  tempRake.ScaleFactor.X = kX;
  tempRake.ScaleFactor.Y = kY;

  return tempRake;

}

BulletPoint CheckTool::CheckPoints(const QVector<BulletPoint>& points)
{
  double sumOfX = 0;
  double sumOfY = 0;
  QVector<BulletPoint> pointsFilter;

  int numOfPoints = points.size();

  for (const auto& point : points) {
      sumOfX += point.X;
      sumOfY += point.Y;
    }

  qDebug() << QString("X坐标的归中值: %1,Y坐标的归中: %2 ,点的个数: %3").arg(sumOfX).arg(sumOfY).arg(numOfPoints);

  double avgX = sumOfX * 1.0 / double(numOfPoints * 1.0);
  double avgY = sumOfY * 1.0 / double(numOfPoints * 1.0);

  qDebug() << QString("过滤前点的坐标平均值 avgX: %1, avgY: %2 ").arg(avgX).arg(avgY);
  for(int i = 0;i < points.size();i++) {
      if (std::abs(points[i].X - avgX) > FilterNumber || std::abs(points[i].Y - avgY) > FilterNumber) {
          qDebug() << QString("被过滤的点: (%1, %2)").arg(points[i].X).arg(points[i].Y);
          continue;
        } else {

          pointsFilter.push_back(points[i]);
        }
    }

  int numOfPointsFilter = pointsFilter.size();

  qDebug() << QString("过滤后长度：%1").arg(numOfPointsFilter);

  sumOfX = 0;
  sumOfY = 0;

  for (const auto& point : pointsFilter) {
      sumOfX += point.X;
      sumOfY += point.Y;
    }

  BulletPoint point;

  point.X = sumOfX * 1.0 / double(numOfPointsFilter * 1.0);
  point.Y = sumOfY * 1.0 / double(numOfPointsFilter * 1.0);

  return point;
}

bool CheckTool::IsInner(double num, double less, int more)
{
  return (num >= less) && (num <= more);
}

bool CheckTool::checkDataIsLegal(const Rake &tempRake)
{
  bool ret = IsInner(tempRake.LeftDownPoint.X, 0.0, 9000) &&
      IsInner(tempRake.LeftDownPoint.Y, 0.0, 9000) &&
      IsInner(tempRake.RightUpPoint.X, 0.0, 9000) &&
      IsInner(tempRake.RightUpPoint.Y, 0.0, 9000);
  // 合法返回ture
  return ret;
}
